home *** CD-ROM | disk | FTP | other *** search
/ TeX 1995 July / TeX CD-ROM July 1995 (Disc 1)(Walnut Creek)(1995).ISO / dviware / dvibook / libtex / seek.c < prev    next >
C/C++ Source or Header  |  1994-03-18  |  3KB  |  148 lines

  1. /*
  2.  * Copyright (c) 1987, 1989 University of Maryland
  3.  * Department of Computer Science.  All rights reserved.
  4.  * Permission to copy for any purpose is hereby granted
  5.  * so long as this copyright notice remains intact.
  6.  */
  7.  
  8. #ifndef lint
  9. static char rcsid[] = "$Header: /usr/src/local/tex/local/mctex/lib/RCS/seek.c,v 3.1 89/08/22 21:59:04 chris Exp $";
  10. #endif
  11.  
  12. /*
  13.  * SeekFile copies an input stdio file, if necessary, so that
  14.  * it produces a stdio file on which fseek() works properly.
  15.  * It returns NULL if this cannot be done; in that case, the
  16.  * input file is closed (or otherwise rendered worthless).
  17.  *
  18.  * CopyFile copies an input file unconditionally.  (On non-Unix
  19.  * machines, it might `accidentally' not copy it.)
  20.  *
  21.  * On Unix machines, this means `if the input is a pipe or tty,
  22.  * copy it to a temporary file'.  On other systems, all stdio files
  23.  * might happen to be seekable.
  24.  */
  25.  
  26. #include <stdio.h>
  27. #include "types.h"        /* for BSD_FILE_SYSTEM */
  28. #include "seek.h"
  29.  
  30. #ifdef EASY_BUT_NOT_GOOD
  31.  
  32. FILE *CopyFile(f) FILE *f; { return (f); }
  33. FILE *SeekFile(f) FILE *f; { return (f); }
  34.  
  35. #else
  36.  
  37. #include <errno.h>
  38. #ifdef BSD_FILE_SYSTEM
  39. #include <sys/param.h>        /* want MAXBSIZE */
  40. #else
  41. #include <sys/types.h>
  42. #endif
  43. #include <sys/stat.h>
  44.  
  45. long    lseek();
  46. char    *malloc();
  47.  
  48. extern int errno;
  49.  
  50. /*
  51.  * Make and return a version of `f' on which fseek works (unconditionally).
  52.  * This code is somewhat Unix-specific.
  53.  */
  54. FILE *
  55. CopyFile(f)
  56.     FILE *f;
  57. {
  58.     register int tf, n, ifd, w;
  59.     register char *p, *buf;
  60.     register int blksize;
  61.     struct stat st;
  62.     int e;
  63. #ifdef MAXBSIZE
  64. #define BSIZE MAXBSIZE
  65. #else
  66. #define BSIZE BUFSIZ
  67. #endif
  68.     char stackbuf[BSIZE];
  69.  
  70.     /* get a read/write temp file which will vanish when closed */
  71.     if ((tf = MakeRWTempFile(stackbuf)) < 0) {
  72.         e = errno;
  73.         (void) fclose(f);
  74.         errno = e;
  75.         return (NULL);
  76.     }
  77.  
  78.     /* compute buffer size and choose buffer */
  79.     ifd = fileno(f);
  80.     buf = stackbuf;
  81.     blksize = sizeof stackbuf;
  82. #ifdef BSD_FILE_SYSTEM
  83.     if (fstat(tf, &st) == 0 && st.st_blksize > blksize) {
  84.         /*
  85.          * The output block size is the important one,
  86.          * but the input block size is not irrelevant.
  87.          *
  88.          * This should actually compute the lcm, but we
  89.          * will rely on block sizes being powers of two
  90.          * (so that the larger is the lcm).
  91.          */
  92.         blksize = st.st_blksize;
  93.         if (fstat(ifd, &st) == 0 && st.st_blksize > blksize)
  94.             blksize = st.st_blksize;
  95.         if ((buf = malloc((unsigned)blksize)) == NULL) {
  96.             buf = stackbuf;
  97.             blksize = sizeof stackbuf;
  98.         }
  99.     }
  100. #endif
  101.     /* copy from input file to temp file */
  102.     (void) lseek(ifd, 0L, 0);    /* paranoia */
  103.     while ((n = read(ifd, p = buf, blksize)) > 0) {
  104.         do {
  105.             if ((w = write(tf, p, n)) < 0) {
  106.                 (void) close(tf);
  107.                 (void) fclose(f);
  108.                 return (NULL);
  109.             }
  110.             p += w;
  111.         } while ((n -= w) > 0);
  112.     }
  113.     e = errno;        /* in case n < 0 */
  114.     if (buf != stackbuf)
  115.         free(buf);
  116.     if (n < 0) {
  117.         (void) close(tf);
  118.         (void) fclose(f);
  119.         errno = e;
  120.         return (NULL);
  121.     }
  122.  
  123.     /* discard the input file, and rewind and open the temporary */
  124.     (void) fclose(f);
  125.     (void) lseek(tf, 0L, 0);
  126.     errno = 0;
  127.     if ((f = fdopen(tf, "r")) == NULL) {
  128.         if (errno == 0)
  129.             e = EMFILE;
  130.         (void) close(tf);
  131.         errno = e;
  132.     }
  133.     return (f);
  134. }
  135.  
  136. /*
  137.  * Copy an input file, but only if necessary.
  138.  */
  139. FILE *SeekFile(f)
  140.     FILE *f;
  141. {
  142.     int fd = fileno(f);
  143.  
  144.     return (lseek(fd, 0L, 1) >= 0 && !isatty(fd) ? f : CopyFile(f));
  145. }
  146.  
  147. #endif /* EASY_BUT_NOT_GOOD */
  148.